/*
 * Copyright (C) 2016 Bilibili
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bilibili.magicasakura.widgets;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentState;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.agp.render.BlendMode;
import ohos.agp.utils.Color;

import com.bilibili.magicasakura.utils.AttrValue;
import com.bilibili.magicasakura.utils.DrawableUtils;
import com.bilibili.magicasakura.utils.ElementTintUtil;
import com.bilibili.magicasakura.utils.ThemeUtils;
import com.bilibili.magicasakura.utils.TintInfo;
import com.bilibili.magicasakura.utils.TintManager;

/**
 * @author xyczero617@gmail.com
 * @time 15/9/26
 */
class AppCompatBackgroundHelper extends AppCompatBaseHelper<Component> {

    private TintInfo mBackgroundTintInfo;

    private Element mBackgroundRes;
    private Color mBackgroundTintRes;
    private Color mBackgroundTintStateRes;

    private int mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom;

    AppCompatBackgroundHelper(Component view, TintManager tintManager) {
        super(view, tintManager);
    }

    @SuppressWarnings("ResourceType")
    @Override
    void loadFromAttribute(AttrSet attrs, int defStyleAttr) {
        initPadding();
        if (attrs.getAttr("backgroundTint").isPresent()) {
            mBackgroundTintRes = AttrValue.get(attrs, "backgroundTint", ThemeUtils.themeColor);
            mBackgroundTintStateRes = AttrValue.get(attrs, "backgroundStateTint", ThemeUtils.themeColor);
            if (attrs.getAttr("backgroundTintMode").isPresent()) {
                setSupportBackgroundTintMode(DrawableUtils.parseTintMode(AttrValue.get(attrs, "backgroundTintMode", 0), null));
            }
            setSupportBackgroundTint();
        } else {
            Element drawable = null;
            mBackgroundRes = AttrValue.get(attrs, "background_element", drawable);
//            if (drawable != null) {
//                setBackgroundDrawable(drawable);
//            }
        }
    }

    /**
     * External use
     *
     * @param background
     */
    public void setBackgroundDrawableExternal(Element background) {
        if (skipNextApply()) return;

        resetTintResource(background);
        setSkipNextApply(false);
        recoverPadding(background);
    }

    public void setBackgroundColor(int color) {
        if (skipNextApply()) return;
        ShapeElement element = new ShapeElement();
        element.setRgbColor(RgbColor.fromArgbInt(ThemeUtils.getColor(mView.getContext(), color)));
        resetTintResource(element);
        mView.setBackground(element);
    }

    public void setBackgroundRes(Element element) {
        if (mBackgroundRes != element) {
            resetTintResource(element);

            if (element != null) {
                setBackgroundDrawable(element);
            }
        }
    }

    public void setBackgroundTintList(Color color, BlendMode mode) {
        if (mBackgroundTintRes.getValue() != color.getValue()) {
            mBackgroundTintRes = color;
            if (mBackgroundTintInfo != null) {
                mBackgroundTintInfo.mHasTintColor = false;
                mBackgroundTintInfo.mTintColor = 0;
            }
            setSupportBackgroundTintMode(mode);
            setSupportBackgroundTint();
        }
    }

    /**
     * Internal use
     *
     * @param drawable drawable
     */
    private void setBackgroundDrawable(Element drawable) {
        if (skipNextApply()) return;

        setBackground(drawable);
//        recoverPadding(drawable);
    }

    private boolean setSupportBackgroundTint() {
        if (mBackgroundTintInfo == null) {
            mBackgroundTintInfo = new TintInfo();
        }
        mBackgroundTintInfo.mHasTintColor = true;
        mBackgroundTintInfo.mTintColor = mTintManager.getReplaceColorValue(mBackgroundTintRes);
        return applySupportBackgroundTint();
    }

    private void setSupportBackgroundTintMode(BlendMode mode) {
        if (mBackgroundTintRes != null && mode != null) {
            if (mBackgroundTintInfo == null) {
                mBackgroundTintInfo = new TintInfo();
            }
            mBackgroundTintInfo.mHasTintMode = true;
            mBackgroundTintInfo.mTintMode = mode;
        }
    }

    private boolean applySupportBackgroundTint() {
        Element backgroundDrawable = mView.getBackgroundElement();
        if (backgroundDrawable != null && mBackgroundTintInfo != null && mBackgroundTintInfo.mHasTintColor) {
            if (backgroundDrawable instanceof StateElement) {
                StateElement compoundDrawable = (StateElement) backgroundDrawable;
                StateElement newElement = new StateElement();
                {
                    //禁止状态下的图片
                    int[] states = {ComponentState.COMPONENT_STATE_DISABLED};
                    int index = compoundDrawable.findStateElementIndex(states);
                    if (index >= 0) {
                        Element element = compoundDrawable.getStateElement(index);
                        if (element != null) {
                            if (element instanceof ShapeElement) {
                                ShapeElement element1 = new ShapeElement();
                                element1.setRgbColor(RgbColor.fromArgbInt(mBackgroundTintInfo.mTintColor));
                                element = element1;
                            } else
                                ElementTintUtil.setColorTint(element, mBackgroundTintInfo.mTintColor);
                        }
                        newElement.addState(states, element);
                    }
                }

                {
                    //按压状态下的图片
                    int[] pressedStates = {ComponentState.COMPONENT_STATE_PRESSED};
                    int pressedIndex = compoundDrawable.findStateElementIndex(pressedStates);
                    if (pressedIndex >= 0) {
                        Element element = compoundDrawable.getStateElement(pressedIndex);
                        if (element != null) {
                            int them = mTintManager.getReplaceColorValue(mBackgroundTintStateRes);
                            if (element instanceof ShapeElement) {
                                ShapeElement element1 = new ShapeElement();
                                element1.setRgbColor(RgbColor.fromArgbInt(them));
                                element = element1;
                            } else {
                                ElementTintUtil.setColorTint(element, them);
                            }
                        }
                        newElement.addState(pressedStates, element);
                    }
                }

                {
                    //正常状态下的图片
                    int[] selectStates = {ComponentState.COMPONENT_STATE_EMPTY};
                    int selectIndex = compoundDrawable.findStateElementIndex(selectStates);
                    if (selectIndex >= 0) {
                        Element element = compoundDrawable.getStateElement(selectIndex);
                        if (element != null) {
                            if (element instanceof ShapeElement) {
                                ShapeElement element1 = new ShapeElement();
                                element1.setRgbColor(RgbColor.fromArgbInt(mBackgroundTintInfo.mTintColor));
                                element = element1;
                            } else {
                                ElementTintUtil.setColorTint(element, mBackgroundTintInfo.mTintColor);
                            }
                        }
                        newElement.addState(selectStates, element);
                    }
                }
                setBackgroundDrawable(newElement);
            } else {
                ElementTintUtil.setColorTint(backgroundDrawable, mBackgroundTintInfo.mTintColor);
                setBackgroundDrawable(backgroundDrawable);
            }
            return true;
        }
        return false;
    }

    private void setBackground(Element backgroundDrawable) {
        mView.setBackground(backgroundDrawable);
    }

    private void resetTintResource(Element element) {
        mBackgroundRes = element;
        mBackgroundTintRes = null;
        if (mBackgroundTintInfo != null) {
            mBackgroundTintInfo.mHasTintColor = false;
            mBackgroundTintInfo.mTintColor = 0;
            mBackgroundTintInfo.mHasTintMode = false;
            mBackgroundTintInfo.mTintMode = null;
        }
    }

    private void initPadding() {
        mPaddingLeft = mView.getPaddingLeft();
        mPaddingTop = mView.getPaddingTop();
        mPaddingRight = mView.getPaddingRight();
        mPaddingBottom = mView.getPaddingBottom();
    }

    private boolean hasPadding() {
        return mPaddingLeft != 0 || mPaddingRight != 0 || mPaddingTop != 0 || mPaddingBottom != 0;
    }

    private void recoverPadding(Element background) {
        if (hasPadding()) {
            mView.setPadding(mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom);
        }
    }

    @Override
    public void tint() {
        if (mBackgroundTintRes != null) {
            setSupportBackgroundTint();
        }
    }

    public interface BackgroundExtensible {
        void setBackgroundTintList(Color color);

        void setBackgroundTintList(Color color, BlendMode mode);
    }
}
